package br.com.nuccitec.jfera.basic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import br.com.nuccitec.jfera.api.IBusinessExecutor;
import br.com.nuccitec.jfera.api.IExecutorMapsManager;
import br.com.nuccitec.jfera.business.IBusinessPrefixExecutor;
import br.com.nuccitec.jfera.business.IBusinessSpecificExecutor;
import br.com.nuccitec.jfera.security.IGeneralSecurityExecutor;
import br.com.nuccitec.jfera.security.ISecurityExecutor;
import br.com.nuccitec.jfera.security.ISecurityPrefixExecutor;
import br.com.nuccitec.jfera.security.ISpecificSecurityExecutor;

public class ExecutorMapsManager implements IExecutorMapsManager {
	final private Map<String, List<ISecurityExecutor>> specificSecurityExecutorMap = new HashMap<String, List<ISecurityExecutor>>();
	final private Map<String, List<ISecurityExecutor>> generalSecurityExecutorMap = new HashMap<String, List<ISecurityExecutor>>();
	final private Map<String, IBusinessExecutor> businessExecutorMap = new HashMap<String, IBusinessExecutor>();
	final private List<IBusinessPrefixExecutor> businessPrefixExecutorList = new ArrayList<IBusinessPrefixExecutor>();
	final private List<ISecurityPrefixExecutor> securityPrefixExecutorList = new ArrayList<ISecurityPrefixExecutor>();
	private boolean addGeneralSecurityExecuted = false;

	ExecutorMapsManager() {
	}

	@Override
	public void addSecurityExecutor(ISpecificSecurityExecutor executor) {
		Logger.getLogger(this.getClass().getName()).info("Setting services with ids: " + executor.getRequestIdsToAttend() + " to " + executor.getClass().getSimpleName());
		for (String e : executor.getRequestIdsToAttend()) {
			List<ISecurityExecutor> executorList = specificSecurityExecutorMap.get(e);
			if (executorList == null) {
				executorList = new ArrayList<ISecurityExecutor>();
				specificSecurityExecutorMap.put(e, executorList);
			}
			if (!executorList.contains(executor)) {
				executorList.add(executor);
			}
		}
	}

	@Override
	public void addBusinessExecutor(IBusinessSpecificExecutor executor) {
		if (addGeneralSecurityExecuted) {
			throw new IllegalStateException("It´s not allowed setting an IBusinessExecutor after calling addSecurityExecutor(IGeneralSecurityExecutor secGenStub) method");
		}
		Logger.getLogger(this.getClass().getName()).info("Setting service with id: " + executor.getRequestIdToAttend() + " to " + executor.getClass().getSimpleName());
		businessExecutorMap.put(executor.getRequestIdToAttend(), executor);
	}

	@Override
	public IBusinessExecutor getBusinessExecutor(String e) {
		return businessExecutorMap.get(e);
	}

	@Override
	public List<ISecurityExecutor> getSpecificSecurityExecutors(String id) {
		List<ISecurityExecutor> specificList = specificSecurityExecutorMap.get(id);
		return specificList;
	}

	@Override
	public void addSecurityExecutor(IGeneralSecurityExecutor generalSecurityExecutor) {
		Logger.getLogger(this.getClass().getName()).info(
				"Setting services with ids: " + generalSecurityExecutor.getClass().getSimpleName() + ", but those with ids:  " + generalSecurityExecutor.getRequestIdsToNotAttend());
		addGeneralSecurityExecuted = true;
		for (String key : businessExecutorMap.keySet()) {
			if (!generalSecurityExecutor.getRequestIdsToNotAttend().contains(key)) {
				List<ISecurityExecutor> executorList = generalSecurityExecutorMap.get(key);
				if (executorList == null) {
					executorList = new ArrayList<ISecurityExecutor>();
				}
				executorList.add(generalSecurityExecutor);
				generalSecurityExecutorMap.put(key, executorList);
			}
		}
	}

	@Override
	public List<ISecurityExecutor> getGeneralSecurityExecutors(String id) {
		return generalSecurityExecutorMap.get(id);
	}

	@Override
	public IBusinessExecutor getBusinessPrefixExecutor(String businessPrefixedRequest) {
		for (IBusinessPrefixExecutor e : businessPrefixExecutorList) {
			if (businessPrefixedRequest.startsWith(e.requestPrefixToAttend())) {
				return e;
			}
		}
		return null;
	}

	@Override
	public void addBusinessPrefixExecutor(IBusinessPrefixExecutor busiPrefix) {
		Logger.getLogger(this.getClass().getName()).info("Setting services with prefix: " + busiPrefix.requestPrefixToAttend() + " to " + busiPrefix.getClass().getSimpleName());
		businessPrefixExecutorList.add(busiPrefix);
	}

	@Override
	public void addSecurityPrefixExecutor(ISecurityPrefixExecutor secPrefix) {
		Logger.getLogger(this.getClass().getName()).info("Setting security for services with prefix: " + secPrefix.requestPrefixToAttend() + " to " + secPrefix.getClass().getSimpleName());
		securityPrefixExecutorList.add(secPrefix);
	}

	@Override
	public List<ISecurityExecutor> getSecurityPrefixExecutors(String requestID) {
		ArrayList<ISecurityExecutor> l = new ArrayList<ISecurityExecutor>();
		for (ISecurityPrefixExecutor s : securityPrefixExecutorList) {
			if (requestID.startsWith(s.requestPrefixToAttend())) {
				l.add(s);
			}
		}
		return l;
	}
}
